
/*
STL（Standard Template Library），即标准模板库，是一个具有工业强度的，高效的C++程序库。

STL的一个重要特点是数据结构和算法的分离。尽管这是个简单的概念，但这种分离确实使得STL变得非常通用。例如，由于STL的sort()函数是完全通用的，你可以用它来操作几乎任何数据集合，包括链表，容器和数组；


STL另一个重要特性是它不是面向对象的。为了具有足够通用性，STL主要依赖于模板而不是封装，继承和虚函数（多态性）——OOP的三个要素。
由于STL是基于模板，内联函数的使用使得生成的代码短小高效；

从逻辑层次来看，在STL中体现了泛型化程序设计的思想，引入了诸多新的名词，比如像需求（requirements），
概念（concept），模型（model），容器（container），算法（algorithmn），迭代子（iterator）等。

STL中六大组件：

    容器（Container），是一种数据结构，如list，vector，和deques ，以模板类的方法提供。为了访问容器中的数据，可以使用由容器类输出的迭代器；
    迭代器（Iterator），提供了访问容器中对象的方法。例如，可以使用一对迭代器指定list或vector中的一定范围的对象。
            迭代器就如同一个指针。事实上，C++的指针也是一种迭代器。但是，迭代器也可以是那些定义了operator*()以及其他类似于指针的操作符地方法的类对象；
    算法（Algorithm），是用来操作容器中的数据的模板函数。例如，STL用sort()来对一个vector中的数据进行排序，
            用find()来搜索一个list中的对象，函数本身与他们操作的数据的结构和类型无关，因此他们可以在从简单数组到高度复杂容器的任何数据结构上使用；
    仿函数（Functor）
    适配器（Adaptor）
    分配器（allocator）

    容器（Container）:
    （1）序列式容器（Sequence containers）,每个元素都有固定位置－－取决于插入时机和地点，和元素值无关
     Vector：将元素置于一个动态数组中加以管理，可以随机存取元素（用索引直接存取），数组尾部添加或移除元素非常快速。但是在中部或头部安插元素比较费时；
       Deque：是“double-ended queue”的缩写，可以随机存取元素（用索引直接存取），数组头部和尾部添加或移除元素都非常快速。但是在中部或头部安插元素比较费时；
       List：双向链表，不提供随机存取（按顺序走到需存取的元素，O(n)），在任何位置上执行插入或删除动作都非常迅速，内部只需调整一下指针；
    （2）关联式容器（Associated containers），元素位置取决于特定的排序准则，和插入顺序无关
     Set/Multiset：内部的元素依据其值自动排序，Set内的相同数值的元素只能出现一次，Multisets内可包含多个数值相同的元素，内部由二叉树实现，便于查找；
       Map/Multimap：Map的元素是成对的键值/实值，内部的元素依据其值自动排序，Map内的相同数值的元素只能出现一次，Multimaps内可包含多个数值相同的元素，内部由二叉树实现，便于查找；

    容器类自动申请和释放内存，无需new和delete操作。

    terator（迭代器）模式又称Cursor（游标）模式，用于提供一种方法顺序访问一个聚合对象中各个元素, 而又不需暴露该对象的内部表示。
    Iterator模式是运用于聚合对象的一种模式，通过运用该模式，使得我们可以在不知道对象内部表示的情况下，按照一定顺序（由iterator提供的方法）访问聚合对象中的各个元素。

    


*/

/*

算法部分主要由头文件<algorithm>，<numeric>和<functional>组成。
    STL提供了大约100个实现算法的模版函数，比如算法for_each将为指定序列中的每一个元素调用指定的函数，stable_sort以你所指定的规则对序列进行稳定性排序等等。
所有算法进行细致分类并标明功能：
<一>查找算法(13个)：判断容器中是否包含某个值
adjacent_find:   在iterator对标识元素范围内，查找一对相邻重复元素，找到则返回指向这对元素的第一个元素的                                                 ForwardIterator。否则返回last。重载版本使用输入的二元操作符代替相等的判断。
binary_search: 在有序序列中查找value，找到返回true。重载的版本实用指定的比较函数对象或函数指针来判断相等。
count:                利用等于操作符，把标志范围内的元素与输入值比较，返回相等元素个数。
count_if:            利用输入的操作符，对标志范围内的元素进行操作，返回结果为true的个数。
equal_range:     功能类似equal，返回一对iterator，第一个表示lower_bound，第二个表示upper_bound。
find:                   利用底层元素的等于操作符，对指定范围内的元素与输入值进行比较。当匹配时，结束搜索，返回该元素的                               一个InputIterator。
find_end:          在指定范围内查找"由输入的另外一对iterator标志的第二个序列"的最后一次出现。找到则返回最后一对的第一                            个ForwardIterator，否则返回输入的"另外一对"的第一个ForwardIterator。重载版本使用用户输入的操作符代                               替等于操作。
find_first_of:     在指定范围内查找"由输入的另外一对iterator标志的第二个序列"中任意一个元素的第一次出现。重载版本中使                             用了用户自定义操作符。
find_if:               使用输入的函数代替等于操作符执行find。
lower_bound:   返回一个ForwardIterator，指向在有序序列范围内的可以插入指定值而不破坏容器顺序的第一个位置。重载函                             数使用自定义比较操作。
upper_bound:  返回一个ForwardIterator，指向在有序序列范围内插入value而不破坏容器顺序的最后一个位置，该位置标志                               一个大于value的值。重载函数使用自定义比较操作。
search:              给出两个范围，返回一个ForwardIterator，查找成功指向第一个范围内第一次出现子序列(第二个范围)的位                                 置，查找失败指向last1。重载版本使用自定义的比较操作。
search_n:          在指定范围内查找val出现n次的子序列。重载版本使用自定义的比较操作。
<二>排序和通用算法(14个)：提供元素排序策略
inplace_merge:      合并两个有序序列，结果序列覆盖两端范围。重载版本使用输入的操作进行排序。
merge:                    合并两个有序序列，存放到另一个序列。重载版本使用自定义的比较。
nth_element:          将范围内的序列重新排序，使所有小于第n个元素的元素都出现在它前面，而大于它的都出现在后面。重                                    载版本使用自定义的比较操作。
partial_sort:            对序列做部分排序，被排序元素个数正好可以被放到范围内。重载版本使用自定义的比较操作。
partial_sort_copy: 与partial_sort类似，不过将经过排序的序列复制到另一个容器。
partition:                 对指定范围内元素重新排序，使用输入的函数，把结果为true的元素放在结果为false的元素之前。
random_shuffle:    对指定范围内的元素随机调整次序。重载版本输入一个随机数产生操作。
reverse:                  将指定范围内元素重新反序排序。
reverse_copy:        与reverse类似，不过将结果写入另一个容器。
rotate:                     将指定范围内元素移到容器末尾，由middle指向的元素成为容器第一个元素。
rotate_copy:           与rotate类似，不过将结果写入另一个容器。
sort:                         以升序重新排列指定范围内的元素。重载版本使用自定义的比较操作。
stable_sort:            与sort类似，不过保留相等元素之间的顺序关系。
stable_partition:    与partition类似，不过不保证保留容器中的相对顺序。
<三>删除和替换算法(15个)
copy:                    复制序列
copy_backward: 与copy相同，不过元素是以相反顺序被拷贝。
iter_swap:           交换两个ForwardIterator的值。
remove:               删除指定范围内所有等于指定元素的元素。注意，该函数不是真正删除函数。内置函数不适合使用remove和                               remove_if函数。
remove_copy:     将所有不匹配元素复制到一个制定容器，返回OutputIterator指向被拷贝的末元素的下一个位置。
remove_if:           删除指定范围内输入操作结果为true的所有元素。
remove_copy_if: 将所有不匹配元素拷贝到一个指定容器。
replace:               将指定范围内所有等于vold的元素都用vnew代替。
replace_copy:     与replace类似，不过将结果写入另一个容器。
replace_if:           将指定范围内所有操作结果为true的元素用新值代替。
replace_copy_if: 与replace_if，不过将结果写入另一个容器。
swap:                   交换存储在两个对象中的值。
swap_range:       将指定范围内的元素与另一个序列元素值进行交换。
unique:                清除序列中重复元素，和remove类似，它也不能真正删除元素。重载版本使用自定义比较操作。
unique_copy:      与unique类似，不过把结果输出到另一个容器。
<四>排列组合算法(2个)：提供计算给定集合按一定顺序的所有可能排列组合
next_permutation: 取出当前范围内的排列，并重新排序为下一个排列。重载版本使用自定义的比较操作。
prev_permutation: 取出指定范围内的序列并将它重新排序为上一个序列。如果不存在上一个序列则返回false。重载版本使用                                   自定义的比较操作。
<五>算术算法(4个)
accumulate:               iterator对标识的序列段元素之和，加到一个由val指定的初始值上。重载版本不再做加法，而是传进来的                                      二元操作符被应用到元素上。
partial_sum:               创建一个新序列，其中每个元素值代表指定范围内该位置前所有元素之和。重载版本使用自定义操作代                                      替加法。
inner_product:           对两个序列做内积(对应元素相乘，再求和)并将内积加到一个输入的初始值上。重载版本使用用户定义                                        的操作。
adjacent_difference: 创建一个新序列，新序列中每个新值代表当前元素与上一个元素的差。重载版本用指定二元操作计算相                                      邻元素的差。
<六>生成和异变算法(6个)
fill:                 将输入值赋给标志范围内的所有元素。
fill_n:            将输入值赋给first到first+n范围内的所有元素。
for_each:      用指定函数依次对指定范围内所有元素进行迭代访问，返回所指定的函数类型。该函数不得修改序列中的元素。
generate:      连续调用输入的函数来填充指定的范围。
generate_n: 与generate函数类似，填充从指定iterator开始的n个元素。
transform:    将输入的操作作用与指定范围内的每个元素，并产生一个新的序列。重载版本将操作作用在一对元素上，另外一                        个元素来自输入的另外一个序列。结果输出到指定容器。
<七>关系算法(8个)
equal:                                  如果两个序列在标志范围内元素都相等，返回true。重载版本使用输入的操作符代替默认的等于操                                               作符。
includes:                             判断第一个指定范围内的所有元素是否都被第二个范围包含，使用底层元素的<操作符，成功返回                                                true。重载版本使用用户输入的函数。
lexicographical_compare: 比较两个序列。重载版本使用用户自定义比较操作。
max:                                     返回两个元素中较大一个。重载版本使用自定义比较操作。
max_element:                      返回一个ForwardIterator，指出序列中最大的元素。重载版本使用自定义比较操作。
min:                                      返回两个元素中较小一个。重载版本使用自定义比较操作。
min_element:                       返回一个ForwardIterator，指出序列中最小的元素。重载版本使用自定义比较操作。
mismatch:                            并行比较两个序列，指出第一个不匹配的位置，返回一对iterator，标志第一个不匹配元素位置。                                                 如果都匹配，返回每个容器的last。重载版本使用自定义的比较操作。
<八>集合算法(4个)
set_union:                            构造一个有序序列，包含两个序列中所有的不重复元素。重载版本使用自定义的比较操作。
set_intersection:                 构造一个有序序列，其中元素在两个序列中都存在。重载版本使用自定义的比较操作。
set_difference:                    构造一个有序序列，该序列仅保留第一个序列中存在的而第二个中不存在的元素。重载版本使用                                                  自定义的比较操作。
set_symmetric_difference: 构造一个有序序列，该序列取两个序列的对称差集(并集-交集)。
<九>堆算法(4个)
make_heap: 把指定范围内的元素生成一个堆。重载版本使用自定义比较操作。
pop_heap:   并不真正把最大元素从堆中弹出，而是重新排序堆。它把first和last-1交换，然后重新生成一个堆。可使用容器的                       back来访问被"弹出"的元素或者使用pop_back进行真正的删除。重载版本使用自定义的比较操作。
push_heap: 假设first到last-1是一个有效堆，要被加入到堆的元素存放在位置last-1，重新生成堆。在指向该函数前，必须先把                       元素插入容器后。重载版本使用指定的比较操作。
sort_heap:  对指定范围内的序列重新排序，它假设该序列是个有序堆。重载版本使用自定义比较操作。

*/

/*
仿函数(functor)，就是使一个类的使用看上去象一个函数。其实现就是类中实现一个operator()，这个类就有了类似函数的行为，就是一个仿函数类了。

1）C语言使用函数指针和回调函数来实现仿函数
比如，定义一个排序函数。
int sort_function( const void *a, const void *b){...}
使用函数指针来排序：
   int list[5] = { 54, 21, 11, 67, 22 };
   qsort((void *)list, 5, sizeof(list[0]), sort_function);
2）在C++里，我们通过在一个类中重载括号运算符的方法使用一个函数对象而不是一个普通函数。
定义一个类
class display
{
public:
    void operator()(const T &x)  //函数
    {
        cout << x << " ";
    }
};
调用：
    int ia[] = { 1,2,3,4,5 };
    for_each(ia, ia + 5, display<int>());

    要使用STL内建的仿函数，必须包含<functional>头文件
    1）算术类仿函数

               加：plus<T>

               减：minus<T>

               乘：multiplies<T>

               除：divides<T>

               模取：modulus<T>

               否定：negate<T>
 2）关系运算类仿函数

               等于：equal_to<T>

               不等于：not_equal_to<T>

               大于：greater<T>

               大于等于：greater_equal<T>

               小于：less<T>

               小于等于：less_equal<T>
 3）逻辑运算仿函数

                 逻辑与：logical_and<T>

                 逻辑或：logical_or<T>

                 逻辑否：logical_no<T>


*/

/*
标准库提供了三种顺序容器适配器：queue(FIFO队列)、priority_queue(优先级队列)、stack(栈)
适配器是使一种事物的行为类似于另外一种事物行为的一种机制”，适配器对容器进行包装，使其表现出另外一种行为。
例如，stack<int, vector<int> >实现了栈的功能，但其内部使用顺序容器vector<int>来存储数据。（相当于是vector<int>表现出了栈的行为）。

头文件：
    #include <stack>        //stack
    #include<queue>       //queue、priority_queue

stack<int> s;
stack< int, vector<int> > stk;  //覆盖基础容器类型，使用vector实现stk
s.empty();  //判断stack是否为空，为空返回true，否则返回false
s.size();   //返回stack中元素的个数
s.pop();    //删除栈顶元素，但不返回其值
s.top();    //返回栈顶元素的值，但不删除此元素
s.push(item);   //在栈顶压入新元素item


queue<int> q; //priority_queue<int> q;
q.empty();  //判断队列是否为空
q.size();   //返回队列长度
q.push(item);   //对于queue，在队尾压入一个新元素
               //对于priority_queue，在基于优先级的适当位置插入新元素
//queue only:
q.front();  //返回队首元素的值，但不删除该元素
q.back();   //返回队尾元素的值，但不删除该元素
//priority_queue only:
q.top();    //返回具有最高优先级的元素值，但不删除该元素


*/

/*
vector
3.1.1 基本函数实现

1.构造函数

    vector():创建一个空vector
    vector(int nSize):创建一个vector,元素个数为nSize
    vector(int nSize,const t& t):创建一个vector，元素个数为nSize,且值均为t
    vector(const vector&):复制构造函数
    vector(begin,end):复制[begin,end)区间内另一个数组的元素到vector中

2.增加函数

    void push_back(const T& x):向量尾部增加一个元素X
    iterator insert(iterator it,const T& x):向量中迭代器指向元素前增加一个元素x
    iterator insert(iterator it,int n,const T& x):向量中迭代器指向元素前增加n个相同的元素x
    iterator insert(iterator it,const_iterator first,const_iterator last):向量中迭代器指向元素前插入另一个相同类型向量的[first,last)间的数据

3.删除函数

    iterator erase(iterator it):删除向量中迭代器指向元素
    iterator erase(iterator first,iterator last):删除向量中[first,last)中元素
    void pop_back():删除向量中最后一个元素
    void clear():清空向量中所有元素

4.遍历函数

    reference at(int pos):返回pos位置元素的引用
    reference front():返回首元素的引用
    reference back():返回尾元素的引用
    iterator begin():返回向量头指针，指向第一个元素
    iterator end():返回向量尾指针，指向向量最后一个元素的下一个位置
    reverse_iterator rbegin():反向迭代器，指向最后一个元素
    reverse_iterator rend():反向迭代器，指向第一个元素之前的位置

5.判断函数

    bool empty() const:判断向量是否为空，若为空，则向量中无元素

6.大小函数

    int size() const:返回向量中元素的个数
    int capacity() const:返回当前向量张红所能容纳的最大元素值
    int max_size() const:返回最大可允许的vector元素数量值

7.其他函数

    void swap(vector&):交换两个同类型向量的数据
    void assign(int n,const T& x):设置向量中第n个元素的值为x
    void assign(const_iterator first,const_iterator last):向量中[first,last)中元素设置成当前向量元素

8.看着清楚

    1.push_back 在数组的最后添加一个数据

    2.pop_back 去掉数组的最后一个数据

    3.at 得到编号位置的数据

    4.begin 得到数组头的指针

    5.end 得到数组的最后一个单元+1的指针

    6．front 得到数组头的引用

    7.back 得到数组的最后一个单元的引用

    8.max_size 得到vector最大可以是多大

    9.capacity 当前vector分配的大小

    10.size 当前使用数据的大小

    11.resize 改变当前使用数据的大小，如果它比当前使用的大，者填充默认值

    12.reserve 改变当前vecotr所分配空间的大小

    13.erase 删除指针指向的数据项

    14.clear 清空当前的vector

    15.rbegin 将vector反转后的开始指针返回(其实就是原来的end-1)

    16.rend 将vector反转构的结束指针返回(其实就是原来的begin-1)

    17.empty 判断vector是否为空

    18.swap 与另一个vector交换数据

*/

/*
deque

所谓的deque是”double ended queue”的缩写，双端队列不论在尾部或头部插入元素，都十分迅速。而在中间插入元素则会比较费时，因为必须移动中间其他的元素。双端队列是一种随机访问的数据类型，提供了在序列两端快速插入和删除操作的功能，它可以在需要的时候改变自身大小，完成了标准的C++数据结构中队列的所有功能。

Vector是单向开口的连续线性空间，deque则是一种双向开口的连续线性空间。deque对象在队列的两端放置元素和删除元素是高效的，而向量vector只是在插入序列的末尾时操作才是高效的。deque和vector的最大差异，一在于deque允许于常数时间内对头端进行元素的插入或移除操作，二在于deque没有所谓的capacity观念，因为它是动态地以分段连续空间组合而成，随时可以增加一段新的空间并链接起来。换句话说，像vector那样“因旧空间不足而重新配置一块更大空间，然后复制元素，再释放旧空间”这样的事情在deque中是不会发生的。也因此，deque没有必要提供所谓的空间预留（reserved）功能。

虽然deque也提供Random Access Iterator，但它的迭代器并不是普通指针，其复杂度和vector不可同日而语，这当然涉及到各个运算层面。因此，除非必要，我们应尽可能选择使用vector而非deque。对deque进行的排序操作，为了最高效率，可将deque先完整复制到一个vector身上，将vector排序后（利用STL的sort算法），再复制回deque。

deque是一种优化了的对序列两端元素进行添加和删除操作的基本序列容器。通常由一些独立的区块组成，第一区块朝某方向扩展，最后一个区块朝另一方向扩展。它允许较为快速地随机访问但它不像vector一样把所有对象保存在一个连续的内存块，而是多个连续的内存块。并且在一个映射结构中保存对这些块以及顺序的跟踪。
3.2.1 声明deque容器

    #include<deque>  // 头文件
    deque<type> deq;  // 声明一个元素类型为type的双端队列que
    deque<type> deq(size);  // 声明一个类型为type、含有size个默认值初始化元素的的双端队列que
    deque<type> deq(size, value);  // 声明一个元素类型为type、含有size个value元素的双端队列que
    deque<type> deq(mydeque);  // deq是mydeque的一个副本
    deque<type> deq(first, last);  // 使用迭代器first、last范围内的元素初始化deq

3.2.2 deque的常用成员函数

deque<int> deq;

    deq[ ]：用来访问双向队列中单个的元素。
    deq.front()：返回第一个元素的引用。
    deq.back()：返回最后一个元素的引用。
    deq.push_front(x)：把元素x插入到双向队列的头部。
    deq.pop_front()：弹出双向队列的第一个元素。
    deq.push_back(x)：把元素x插入到双向队列的尾部。
    deq.pop_back()：弹出双向队列的最后一个元素。

3.2.3 deque的一些特点

    支持随机访问，即支持[ ]以及at()，但是性能没有vector好。
    可以在内部进行插入和删除操作，但性能不及list。
    deque两端都能够快速插入和删除元素，而vector只能在尾端进行。
    deque的元素存取和迭代器操作会稍微慢一些，因为deque的内部结构会多一个间接过程。
    deque迭代器是特殊的智能指针，而不是一般指针，它需要在不同的区块之间跳转。
    deque可以包含更多的元素，其max_size可能更大，因为不止使用一块内存。
    deque不支持对容量和内存分配时机的控制。
    在除了首尾两端的其他地方插入和删除元素，都将会导致指向deque元素的任何pointers、references、iterators失效。不过，deque的内存重分配优于vector，因为其内部结构显示不需要复制所有元素。
    deque的内存区块不再被使用时，会被释放，deque的内存大小是可缩减的。不过，是不是这么做以及怎么做由实际操作版本定义。
    deque不提供容量操作：capacity()和reverse()，但是vector可以。

*/
#include <list>
#include <vector>
#include <iostream>
#include <algorithm>
#include <numeric>
#include<functional>
#include <vector> 

#include<stack>
#include <map> 

using namespace std;

namespace stlDemo {

    bool compare(int a, int b)
    {
        return a < b; //升序排列，如果改为return a>b，则为降序 
    }
    void demo1()
    {
        int a[20] = { 2,4,1,23,5,76,0,43,24,65 }, i;
        for (i = 0; i < 20; i++)
            cout << a[i] << endl;
        sort(a, a + 20, compare);

    }
    template<typename T>
    class display
    {
    public:
        void operator()(const T& x)
        {
            cout << x << " ";
        }
    };
    int main()
    {
        {
            cout << " accumulate(iv.begin(), iv.end(), 1, multiplies<int>()) \n";
            int ia[] = { 1,2,3,4,5 };
            vector<int> iv(ia, ia + 5);
            //120
            cout << accumulate(iv.begin(), iv.end(), 1, multiplies<int>()) << endl;
            //15
            cout << multiplies<int>()(3, 5) << endl;

            modulus<int>  modulusObj;
            cout << modulusObj(3, 5) << endl; // 3 

        }
        {
            cout << "\n for_each(iv.begin(), iv.end(), display<int>()); \n";
            int ia[] = { 1,5,4,3,2 };
            vector<int> iv(ia, ia + 5);
            sort(iv.begin(), iv.end(), greater<int>());
            for_each(iv.begin(), iv.end(), display<int>());
        }

        {
            cout << "\n obj.push_back(i)  obj.pop_back(); \n";
            vector<int>obj;//创建一个向量存储容器 int
            for (int i = 0; i < 10; i++) // push_back(elem)在数组最后添加数据 
            {
                obj.push_back(i);
                cout << obj[i] << ",";
            }

            for (int i = 0; i < 5; i++)//去掉数组最后一个数据 
            {
                obj.pop_back();
            }

            cout << "\n" << endl;

            for (int i = 0; i < obj.size(); i++)//size()容器中实际数据个数 
            {
                cout << obj[i] << ",";
            }
            obj.clear();//清除容器中所以数据

        }
        {
            wcout << L"\n\n sort(obj.begin(), obj.end());//从小到大 \n";
            vector<int>obj;

            obj.push_back(1);
            obj.push_back(3);
            obj.push_back(0);

            sort(obj.begin(), obj.end());//从小到大

            wcout << L"从小到大:" << endl;
            for (int i = 0; i < obj.size(); i++)
            {
                cout << obj[i] << ",";
            }

            cout << "\n" << endl;

            wcout << L"从大到小:" << endl;
            reverse(obj.begin(), obj.end());//从大到小 
            for (int i = 0; i < obj.size(); i++)
            {
                cout << obj[i] << ",";
            }

            demo1();//自定义排序函数，从大到小
        }

        {
            wcout << L"\n\n顺序访问\n\n";
            //顺序访问
            vector<int>obj;
            for (int i = 0; i < 10; i++)
            {
                obj.push_back(i);
            }

            wcout << L"直接利用数组：\n";
            for (int i = 0; i < 10; i++)//方法一 
            {
                cout << obj[i] << " ";
            }

            cout << endl;
            wcout << L"利用迭代器：vector<int>::iterator it \n";
            //方法二，使用迭代器将容器中数据输出 
            vector<int>::iterator it;//声明一个迭代器，来访问vector容器，作用：遍历或者指向vector容器的元素 
            for (it = obj.begin(); it != obj.end(); it++)
            {
                cout << *it << " ";
            }
        }

        //二维数组两种定义方法（结果一样）
        {
            wcout << L"\n\n二维数组两种定义方法\n\n";
            {
                int N = 5, M = 6;
                vector<vector<int> > obj(N); //定义二维动态数组大小5行 
                for (int i = 0; i < obj.size(); i++)//动态二维数组为5行6列，值全为0 
                {
                    obj[i].resize(M);
                }

                for (int i = 0; i < obj.size(); i++)//输出二维动态数组 
                {
                    for (int j = 0; j < obj[i].size(); j++)
                    {
                        cout << obj[i][j] << " ";
                    }
                    cout << "\n";
                }
            }
            {
                int N = 5, M = 6;
                vector<vector<int> > obj(N, vector<int>(M)); //定义二维动态数组5行6列 

                for (int i = 0; i < obj.size(); i++)//输出二维动态数组 
                {
                    for (int j = 0; j < obj[i].size(); j++)
                    {
                        cout << obj[i][j] << " ";
                    }
                    cout << "\n";
                }
            }
        }
        {
            wcout << L"\n\ndeque是”double ended queue”的缩写，双端队列不论在尾部或头部插入元素，都十分迅速。而在中间插入元素则会比较费时，因为必须移动中间其他的元素\n\n";
            int i;
            int a[10] = { 0,1,2,3,4,5,6,7,8,9 };
            deque<int> q;
            for (i = 0; i <= 9; i++)
            {
                if (i % 2 == 0)
                    q.push_front(a[i]);
                else
                    q.push_back(a[i]);
            }                                  /*此时队列里的内容是: {8,6,4,2,0,1,3,5,7,9}*/
            q.pop_front();
            printf("%d\n", q.front());    /*清除第一个元素后输出第一个(6)*/
            q.pop_back();
            printf("%d\n", q.back());     /*清除最后一个元素后输出最后一个(7)*/
            deque<int>::iterator it;
            for (it = q.begin(); it != q.end(); it++) {
                cout << *it << '\t';
            }
            cout << endl;
        }


        {
            wcout << L"\n\nList是stl实现的双向链表，与向量(vectors)相比, 它允许快速的插入和删除，但是随机访问却比较慢。\n\n";
            typedef list<int> LISTINT;
            typedef list<int> LISTCHAR;
            //用LISTINT创建一个list对象
            LISTINT listOne;
            //声明i为迭代器
            LISTINT::iterator i;

            listOne.push_front(3);
            listOne.push_front(2);
            listOne.push_front(1);

            listOne.push_back(4);
            listOne.push_back(5);
            listOne.push_back(6);

            cout << "listOne.begin()--- listOne.end():" << endl;
            for (i = listOne.begin(); i != listOne.end(); ++i)
                cout << *i << " ";
            cout << endl;

            LISTINT::reverse_iterator ir;
            cout << "listOne.rbegin()---listOne.rend():" << endl;
            for (ir = listOne.rbegin(); ir != listOne.rend(); ir++) {
                cout << *ir << " ";
            }
            cout << endl;

            int result = accumulate(listOne.begin(), listOne.end(), 0);
            cout << "Sum=" << result << endl;
            cout << "------------------" << endl;

            //用LISTCHAR创建一个list对象
            LISTCHAR listTwo;
            //声明i为迭代器
            LISTCHAR::iterator j;

            listTwo.push_front('C');
            listTwo.push_front('B');
            listTwo.push_front('A');

            listTwo.push_back('D');
            listTwo.push_back('E');
            listTwo.push_back('F');

            cout << "listTwo.begin()---listTwo.end():" << endl;
            for (j = listTwo.begin(); j != listTwo.end(); ++j)
                cout << char(*j) << " ";
            cout << endl;

            j = max_element(listTwo.begin(), listTwo.end());
            cout << "The maximum element in listTwo is: " << char(*j) << endl;
        }
        {
            wcout << L"\n\nmap的键值key不可重复，而multimap可以，也正是由于这种区别，map支持[ ]运算符，multimap不支持[ ]运算符。在用法上没什么区别。\n"
                "插入pair数据\n\n";
            map<int, string> mapStudent;
            mapStudent.insert(pair<int, string>(1, "student_one"));
            mapStudent.insert(pair<int, string>(2, "student_two"));
            mapStudent.insert(pair<int, string>(3, "student_three"));
            map<int, string>::iterator iter;
            for (iter = mapStudent.begin(); iter != mapStudent.end(); iter++)
                cout << iter->first << ' ' << iter->second << endl;
        }
        {
            
                wcout << L"\n\n插入value_type数据\n\n";
            map<int, string> mapStudent;
            mapStudent.insert(map<int, string>::value_type(1, "student_one"));
            mapStudent.insert(map<int, string>::value_type(2, "student_two"));
            mapStudent.insert(map<int, string>::value_type(3, "student_three"));
            map<int, string>::iterator iter;
            for (iter = mapStudent.begin(); iter != mapStudent.end(); iter++)
                cout << iter->first << ' ' << iter->second << endl;
        }
        {
            wcout << L"\n\ninsert共有4个重载函数：\n\n"
               " // 插入单个键值对，并返回插入位置和成功标志，插入位置已经存在值时，插入失败 \n"
              "  pair<iterator, bool> insert(const value_type & val); \n"

          "  //在指定位置插入，在不同位置插入效率是不一样的，因为涉及到重排 \n"
          "  iterator insert(const_iterator position, const value_type& val); \n"

         "   // 插入多个 \n"
          "  void insert(InputIterator first, InputIterator last); \n"

           " //c++11开始支持，使用列表插入多个    \n"
          "  void insert(initializer_list<value_type> il); \n"
                ;
            std::map<char, int> mymap;

            // 插入单个值
            mymap.insert(std::pair<char, int>('a', 100));
            mymap.insert(std::pair<char, int>('z', 200));

            //返回插入位置以及是否插入成功
            std::pair<std::map<char, int>::iterator, bool> ret;
            ret = mymap.insert(std::pair<char, int>('z', 500));
            if (ret.second == false) {
                std::cout << "element 'z' already existed";
                std::cout << " with a value of " << ret.first->second << '\n';
            }

            //指定位置插入
            std::map<char, int>::iterator it = mymap.begin();
            mymap.insert(it, std::pair<char, int>('b', 300));  //效率更高
            mymap.insert(it, std::pair<char, int>('c', 400));  //效率非最高

            //范围多值插入
            std::map<char, int> anothermap;
            anothermap.insert(mymap.begin(), mymap.find('c'));

            // 列表形式插入
            anothermap.insert({ { 'd', 100 }, {'e', 200} });

        }
        {
            wcout << L"\n\n用数组方式插入数据\n\n";
            map<int, string> mapStudent;
            mapStudent[1] = "student_one";
            mapStudent[2] = "student_two";
            mapStudent[3] = "student_three";
            map<int, string>::iterator iter;
            for (iter = mapStudent.begin(); iter != mapStudent.end(); iter++)
                cout << iter->first << ' ' << iter->second << endl;
        }
        return 0;
    }
}
